/*
 * Created on Feb 1, 2004
 */
package com.unash.z3950.query;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.xml.sax.SAXException;

import com.unash.util.Consts;
import com.unash.z3950.pdu.AttributeList;
import com.unash.z3950.pdu.AttributeValue;
import com.unash.z3950.pdu.AttributesPlusTerm;
import com.unash.z3950.pdu.Complex;
import com.unash.z3950.pdu.Numeric;
import com.unash.z3950.pdu.OperatorAnd;
import com.unash.z3950.pdu.OperatorAndNot;
import com.unash.z3950.pdu.OperatorOr;
import com.unash.z3950.pdu.ProximityOperator;
import com.unash.z3950.pdu.RPNQuery;
import com.unash.z3950.pdu.RPNStructure;
import com.unash.z3950.pdu.ResultSetId;
import com.unash.z3950.pdu.ResultSetPlusAttributes;
import com.unash.z3950.pdu.RpnRpnOp;
import com.unash.z3950.pdu.Term;
import com.unash.z3950.pdu.Term_CharacterString;
import com.unash.z3950.pdu.Term_General;
import com.unash.z3950.pdu.Term_Null;
import com.unash.z3950.pdu.Term_Numeric;
import com.unash.z3950.pdu.Term_OID;

/**
 * @author Ashwini Gokhale
 */
public class RPNProcessor implements Consts{
	private static List<String> listOfTblNames;
	private static String whereClause;
	private static List<String> listOfResultSets;
	
	public static String getSql(RPNQuery rpnQuery)
	throws IOException,SAXException{
		listOfTblNames = new ArrayList<String>();
		listOfResultSets = new ArrayList<String>();
		whereClause = processRpnStructure(rpnQuery.getRpn());
		String[] tables = (String[])listOfTblNames.toArray(new String[0]);
		StringBuffer from = new StringBuffer();
		from.append(tables[0]);
		for(int i=1;i<listOfTblNames.size();i++){
			from.append(",");
			from.append(tables[i]);
		}//for
		
		 
		String sql = "Select * from " + from.toString() + " where " + whereClause;
		return sql;
	}//getSql
	
	public static String processRpnStructure(RPNStructure rpnStructure)
	throws IOException,SAXException{
		String sql = null;
		AttributeSetBib1 attrSetBib1 = AttributeSetBib1.getInstance();
		if(rpnStructure instanceof RpnRpnOp){
			RpnRpnOp rpnrpnOp = (RpnRpnOp)rpnStructure;
			String rpn1 = processRpnStructure(rpnrpnOp.getRpn1());
			String rpn2 = processRpnStructure(rpnrpnOp.getRpn2());
			
			if(rpnrpnOp.getOp() instanceof OperatorAndNot){
				sql = "(" + rpn1 + " AndNot " + rpn2 + ")";
			}//AndNot
			
			if(rpnrpnOp.getOp() instanceof OperatorAnd){
				sql = "(" + rpn1 + " And " + rpn2 + ")";
			}//And
			
			if(rpnrpnOp.getOp() instanceof OperatorOr){
				sql = "(" + rpn1 + " Or " + rpn2 + ")";
			}//Or
			
			if(rpnrpnOp.getOp() instanceof ProximityOperator){
				//TODO:
			}//ProximityUnitCode

		}//if
		
		
		/*
		 * Assuming that when rpnStructure is instance of attributesplusterm
		 * then attribute list contains only one attribute element.
		 * Assuming AttributeSet = bib1
		 * 
		 */
		if(rpnStructure instanceof  AttributesPlusTerm){
			String termString = null;
			AttributesPlusTerm attributesPlusTerm = (AttributesPlusTerm)rpnStructure;
			
			//bib1
			attributesPlusTerm.getAttributes().getAttributeElement()[0].getAttributeType();
			
			//String term;
			Term term = attributesPlusTerm.getTerm();
			if(term instanceof Term_Null)
				//term = "null";
				System.out.println("Null");
				
			if(term instanceof Term_General){
				System.out.println("general");
				termString = "'" + new String(((Term_General)term).getGeneral().getValue()) + "'";
			}//if
			
			if(term instanceof Term_Numeric)
				System.out.println("Numeric");
			
			if(term instanceof Term_CharacterString)
				System.out.println("characterString");
			
			if(term instanceof Term_OID)
				System.out.println("OID");
				
			/*if(Term instanceof Term_Null)
			if(Term instanceof Term_Null)
			if(Term instanceof Term_Null)*/
			
			AttributeList attrList =  attributesPlusTerm.getAttributes();
			for(int i=0;i<attrList.getAttributeElement().length;i++){
				switch(attrList.getAttributeElement()[i].getAttributeType().getInt()){
					case ATTR_TYPE_USE:
					HashMap databaseMap = attrSetBib1.getDatabaseMap();
					
					
					AttributeValue attrValue = attrList.getAttributeElement()[i].getAttributeValue();
					String attrValueString = null; 
					if(attrValue instanceof Numeric){
						attrValueString = ((Numeric)attrValue).getNumeric().toString();
					}//if
					
					if(attrValue instanceof Complex){
						System.out.println("Complex");
					}//if
					
					DatabaseInfo dbInfo = (DatabaseInfo)databaseMap.get(attrValueString);
					sql = "(" + dbInfo.tblName + "." + dbInfo.colName + " = " + termString + ")";
					
					listOfResultSets.add(dbInfo.tblName);
					
					if(!(listOfTblNames.contains(dbInfo.tblName)))
						listOfTblNames.add(dbInfo.tblName);

					break;
					case ATTR_TYPE_RELATION:
						break;
					case ATTR_TYPE_POSITION:
						break;
					case ATTR_TYPE_STRUCTURE:
						break;
					case ATTR_TYPE_TRUNCATION:
						break;
					case ATTR_TYPE_COMPLETENESS:
						break;
				}//switch
			}//for
			
			return sql;
		}//if
		
		
		if(rpnStructure instanceof  ResultSetId){
			ResultSetId resultSetID = (ResultSetId)rpnStructure;
			listOfResultSets.add(resultSetID.getResultSetId().toString());
		}//if
		
		
		if(rpnStructure instanceof  ResultSetPlusAttributes){
			ResultSetPlusAttributes resultSetPlusAttributes = (ResultSetPlusAttributes)rpnStructure;
			
			if(!(listOfTblNames.contains(resultSetPlusAttributes.getResultSet().toString())))
				listOfTblNames.add(resultSetPlusAttributes.getResultSet().toString());
			
			AttributeList attrList =  resultSetPlusAttributes.getAttributes();
			for(int i=0;i<attrList.getAttributeElement().length;i++){
				switch(attrList.getAttributeElement()[i].getAttributeType().getInt()){
					case ATTR_TYPE_USE:
						break;
					case ATTR_TYPE_RELATION:
						break;
					case ATTR_TYPE_POSITION:
						break;
					case ATTR_TYPE_STRUCTURE:
						break;
					case ATTR_TYPE_TRUNCATION:
						break;
					case ATTR_TYPE_COMPLETENESS:
						break;
				}//switch
			}//for
			//sql = 
		}//if


			
	return sql;	
	}//processRpnStructure
	
}//RPNProcessor
